home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-11-30 | 15.1 KB | 634 lines | [TEXT/KAHL] |
- #include <assert.h>
-
- #include <fstream.h>
- #include <strstream.h>
-
- #include <Types.h>
- #include <Memory.h>
- #include <QuickDraw.h>
- #include <OSUtils.h>
- #include <ToolUtils.h>
- #include <Menus.h>
- #include <Packages.h>
- #include <Traps.h>
- #include <Files.h>
- #include <Aliases.h>
- #include <AppleEvents.h>
- #include <GestaltEqu.h>
- #include <Processes.h>
- #include <Fonts.h>
- #include <OSEvents.h>
- #include <Resources.h>
- #include <Desk.h>
-
- #include <Windows.h>
- #include <QDOffscreen.h>
- #include <SegLoad.h>
- #include <TextEdit.h>
- #include <Folders.h>
-
- #include <PictUtils.h>
-
- #include "gestalt_.h"
- #include "gworld.h"
-
- #include "fsspec.h"
- #include "access_path.h"
- #include "standardfile_.h"
- #include "standardgetfile.h"
- #include "boxmakergetfile.h"
-
- #include "handle.h"
- #include "resource.h"
-
- #include "picture.h"
-
- #include "resourcefile.h"
-
- #include "boxmaker constants.h"
- #include "boxmaker.h"
-
- #include "preferences.cp"
- #include "pixelize.h"
-
- #pragma template_access public
-
- void main();
-
- const short real_modes[ 16] =
- {
- srcCopy, srcOr, srcXor, srcBic,
- notSrcCopy, notSrcOr, notSrcXor, notSrcBic,
- blend, addPin, addOver, subPin,
- addMax, adMax, subOver, adMin
- };
-
- void main()
- {
- pixelize_settings defaultsettings =
- {
- iBlackAndWhite,
- iPictFile,
- useSystemDefault,
- false, // dontCountPixels
- false, // dont suppress Black and White
- false, // not transparent
- true, // do dither
- 0 // srcCopy
- };
- stringhandle prefsFileHandle( 128);
-
- pixelize_shell it( *(Str63 *)*(Handle)prefsFileHandle, defaultsettings);
- it.run();
- }
-
- pixelize_shell::pixelize_shell(
- Str31 prefsFileName, pixelize_settings &defaultsettings)
- : boxmaker( 3000)
- , pixelize_prefs( prefsFileName, defaultsettings)
- {
- folder_depth = 0;
-
- ChangeDepth( whichDepth);
- ChangeStorage( whichStorage);
- ChangeSampling( whichSampling);
- ChangeMode( whichTransfermode);
-
- SetAButton( iCountPixels, countPixels);
- SetAButton( iAlwaysAddBW, alwaysAddBW);
- SetAButton( iTransparent, makeTransparent);
- SetAButton( iDither, dither);
- }
-
- void pixelize_shell::OpenDoc( Boolean opening)
- {
- //
- // WARNING: Ugly long function ahead!
- //
- const OSType theType = theCInfoPBRec.hFileInfo.ioFlFndrInfo.fdType;
- //
- // read in the PICT:
- //
- PicHandle thePICT = 0;
-
- switch( theType)
- {
- case 'PICT':
- thePICT = ReadPictFile( thefsspec);
- break;
-
- case 'pgm5':
- case 'PGM5':
- thePICT = Read_pgm_file( thefsspec);
- break;
-
- default:
- thePICT = ReadPictResource( thefsspec);
- }
- if( thePICT == 0)
- {
- SysBeep( 9);
- } else {
- Rect PICTRect = (**thePICT).picFrame;
- OffsetRect( &PICTRect, -PICTRect.left, -PICTRect.top);
- const short PICTWidth = PICTRect.right;
- const short PICTheight = PICTRect.bottom;
- //
- // Obtain a color table for the resulting PICT:
- //
- CTabHandle theNewColorTable = 0L;
-
- const int requestedDepth = (1 << (whichDepth - 1));
-
- if( requestedDepth == 1)
- {
- theNewColorTable = (CTabHandle)GetResource( 'clut', 1);
- DetachResource( (Handle)theNewColorTable);
- } else {
- switch( whichSampling)
- {
- case useSystemDefault:
- //
- // do we need this or will the gworld get this one, anyway?
- //
- theNewColorTable = (CTabHandle)GetResource( 'clut', requestedDepth);
- DetachResource( (Handle)theNewColorTable);
- break;
-
- default:
- //
- // BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT!
- // BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT!
- // BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT!
- //
- // user-specified selection in a resource. For now, we assume that
- // user-specified resources are numbered consecutive with the
- // system ones. THIS IS A BUG, since nothing is known about the order
- // in which the items are added to the pop-up menu. I repeat:
- //
- // BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT!
- // BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT!
- // BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT!
- //
- case useSystemMethod:
- case usePopularMethod:
- case useMedianMethod:
- const int real_method = systemMethod + (whichSampling - useSystemMethod);
-
- const int requestedColors = (1 << requestedDepth)
- - (2 * alwaysAddBW); // for black and white
- //
- // convert the picture to a pixmap, if 'countPixels' is set.
- // This makes that the 'GetPictInfo' call will do a 'GetPixMapInfo' instead.
- // The default depth for the PixMap is 32. This eats a lot of memory, but
- // ensures a loss-free conversion.
- //
- if( countPixels)
- {
- PicHandle temp = thePICT;
- thePICT = convertToPixMap( temp);
- KillPicture( temp);
- }
- //
- // Obtain color table = Color matching requested => GetPictInfo,
- // else get color table from system.
- //
- // Obtain picture info:
- //
- const short version = 0;
-
- PictInfo thePictInfo;
-
- static const int theAsks[ 2] =
- {
- returnColorTable, returnPalette | suppressBlackAndWhite
- };
- const int toAsk = theAsks[ alwaysAddBW];
-
- if( GetPictInfo( thePICT, &thePictInfo,
- toAsk, requestedColors, real_method, version) == noErr)
- {
- //
- // Build a color table with black and white added:
- //
- if( alwaysAddBW)
- {
- theNewColorTable = AddBlackWhite( thePictInfo.thePalette);
-
- DisposeHandle( (Handle)thePictInfo.thePalette);
- } else {
- theNewColorTable = thePictInfo.theColorTable;
- }
- } else {
- SysBeep( 9);
- }
- break;
- }
- }
- //
- // create the pix map picture:
- //
- short mode = real_modes[ whichTransfermode - 1];
- if( dither)
- {
- mode += ditherCopy;
- }
- PicHandle temp = thePICT;
-
- thePICT = convertToPixMap( temp, requestedDepth, theNewColorTable, makeTransparent, mode);
- KillPicture( temp);
- DisposeHandle( (Handle)theNewColorTable);
- //
- // write the resulting Picture to the file:
- // (Note: the order of WritePictFile, WritePictResource is important;
- // WritePictFile replaces the original files, WritePictResource updates it.
- //
- if( whichStorage != iPICTResource)
- {
- WritePictFile( thefsspec, thePICT);
- (void)thefsspec.SetFType( 'PICT');
- }
- if( whichStorage != iPictFile)
- {
- WritePictResource( thefsspec, thePICT);
- }
- KillPicture( thePICT);
- }
- }
-
- void pixelize_shell::HandleDialogEvent( short itemHit, DialogPtr theDialog)
- {
- switch( itemHit)
- {
- case iBlackAndWhite:
- case i2Bits:
- case i4Bits:
- case i8Bits:
- ChangeDepth( itemHit);
- break;
-
- case iCountPixels:
- countPixels = !countPixels;
- SetAButton( iCountPixels, countPixels);
- break;
-
- case iAlwaysAddBW:
- alwaysAddBW = !alwaysAddBW;
- SetAButton( iAlwaysAddBW, alwaysAddBW);
- break;
-
- case iCLUTSelection:
- {
- short iType;
- Handle iHandle;
- Rect iRect;
- GetDialogItem( gMainDialog, iCLUTSelection, &iType, &iHandle, &iRect);
- whichSampling = GetControlValue( (ControlHandle)iHandle);
- ChangeSampling( whichSampling); // slight overkill, sets control value
- }
- break;
-
- case iTransparent:
- makeTransparent = !makeTransparent;
- SetAButton( iTransparent, makeTransparent);
- break;
-
- case iDither:
- dither = !dither;
- SetAButton( iDither, dither);
- break;
-
- case iTransferMode:
- {
- short iType;
- Handle iHandle;
- Rect iRect;
- GetDialogItem( gMainDialog, iTransferMode, &iType, &iHandle, &iRect);
- whichTransfermode = GetControlValue( (ControlHandle)iHandle);
- }
- break;
-
- case iPictFile:
- case iPICTResource:
- case iBoth:
- ChangeStorage( itemHit);
- break;
- }
- }
-
- void pixelize_shell::ChangeDepth( int newDepth)
- {
- SetOnlyOne( iBlackAndWhite, i8Bits, newDepth);
- whichDepth = newDepth;
- }
-
- void pixelize_shell::ChangeStorage( int newStorage)
- {
- SetOnlyOne( iPictFile, iBoth, newStorage);
- whichStorage = newStorage;
- }
-
- void pixelize_shell::ChangeSampling( int newSampling)
- {
- short iType;
- Handle iHandle;
- Rect iRect;
- GetDialogItem( gMainDialog, iCLUTSelection, &iType, &iHandle, &iRect);
- SetControlValue( (ControlHandle)iHandle, newSampling);
-
- whichSampling = newSampling;
-
- const int theHilite = (whichSampling == useSystemDefault) ? 255 : 0;
-
- GetDialogItem( gMainDialog, iCountPixels, &iType, &iHandle, &iRect);
- HiliteControl( (ControlHandle)iHandle, theHilite);
-
- GetDialogItem( gMainDialog, iAlwaysAddBW, &iType, &iHandle, &iRect);
- HiliteControl( (ControlHandle)iHandle, theHilite);
- }
-
- void pixelize_shell::ChangeMode( int newTransfermode)
- {
- short iType;
- Handle iHandle;
- Rect iRect;
- GetDialogItem( gMainDialog, iTransferMode, &iType, &iHandle, &iRect);
- SetControlValue( (ControlHandle)iHandle, newTransfermode);
-
- whichTransfermode = newTransfermode;
- }
-
- void pixelize_shell::SetAButton( short theItem, Boolean theValue) const
- {
- short iType;
- Handle iHandle;
- Rect iRect;
- GetDialogItem( gMainDialog, theItem, &iType, &iHandle, &iRect);
- SetControlValue( (ControlHandle)iHandle, theValue);
- }
-
- void pixelize_shell::SetOnlyOne( short firstItem, short lastItem, short ItemToSet)
- {
- short iType;
- Handle iHandle;
- Rect iRect;
-
- for( int i = firstItem; i <= lastItem; i++)
- {
- GetDialogItem( gMainDialog, i, &iType, &iHandle, &iRect);
- SetControlValue( (ControlHandle)iHandle, (i == ItemToSet));
- }
- }
-
- PicHandle pixelize_shell::ReadPictFile( const fsspec &thefsspec) const
- {
- PicHandle result = 0;
- access_path thefile( thefsspec, fsRdPerm);
-
- OSErr err = thefile();
-
- long picture_size = 0;
- err = thefile.GetEOF( &picture_size);
-
- picture_size -= 0x0200;
-
- err = thefile.SetFPos( 0x0200);
-
- if( err == noErr)
- {
- result = (PicHandle)NewHandle( picture_size);
- HLock( (Handle)result);
- err = thefile.Read( &picture_size, (char *)*result);
- HUnlock( (Handle)result);
- if( err != noErr)
- {
- DisposeHandle( (Handle)result);
- result = 0;
- }
- }
- err = thefile.Close();
-
- return result;
- }
-
- PicHandle pixelize_shell::ReadPictResource( const fsspec &thefsspec) const
- {
- PicHandle result = 0;
- resourcefile thefile( thefsspec);
-
- OSErr err = thefile.Open( fsRdPerm);
-
- if( err == noErr)
- {
- result = (PicHandle)Get1IndResource( 'PICT', 1);
- DetachResource( (Handle) result);
- }
- err = thefile.Close();
-
- return result;
- }
-
- PicHandle pixelize_shell::Read_pgm_file( const fsspec &thefsspec) const
- {
- PicHandle result = 0;
- access_path thefile( thefsspec, fsRdPerm);
-
- OSErr err = thefile();
-
- if( err == noErr)
- {
- #define maxLength 200
- typedef struct pgm
- {
- short P5;
- char firstLine[ maxLength];
- } pgm;
- struct pgm thePGM;
- long count = sizeof( pgm);
- err = thefile.Read( &count, &thePGM);
-
- if( (err == noErr) && (thePGM.P5 == 'P5'))
- {
- //
- // Read the fields Xres, Yres, max value:
- //
- istrstream in( thePGM.firstLine, maxLength);
-
- short maxX;
- short maxY;
- short maxVal;
-
- in >> maxX >> maxY >> maxVal;
- //
- // Find the line break:
- //
- for( int i = 0; i < maxLength; i++)
- {
- const char c = thePGM.firstLine[ i];
-
- if( (c == '¥n') || (c == '¥r'))
- {
- break;
- }
- }
- err = thefile.SetFPos( i + 1 + 2); // 1 for '¥n', 2 for 'P5'
-
- CTabHandle grays = (CTabHandle)Get1Resource( 'clut', 129);
- gworld offscreen( maxX, maxY, 8, true, grays);
- //
- // Stuff the binary data in the offscreen bitmap
- //
- PixMapPtr thePix = offscreen.get_pixH();
-
- Ptr baseAddr = thePix->baseAddr;
- const short rowBytes = (thePix->rowBytes) & (~0xC000);
- //
- // Read in the binary data:
- //
- for( int y = 0; (y < maxY) && (err == noErr); y++)
- {
- long numtoRead = maxX;
- err = thefile.Read( &numtoRead, baseAddr);
- baseAddr += rowBytes;
- }
- //
- // LockPixels( thePix); not needed; gworld does this
- //
- // Convert the thing to a picture:
- //
- result = offscreen.makePICT();
- }
- }
- err = thefile.Close();
-
- return result;
- }
-
- CTabHandle pixelize_shell::AddBlackWhite( const PaletteHandle thePalette) const
- {
- const int numToAdd = (**thePalette).pmEntries;
- //
- // Build a color table with black and white added:
- //
- PaletteHandle newPalette = GetNewPalette( 128); // contains black and white
-
- ResizePalette( newPalette, numToAdd + 2);
- CopyPalette( thePalette, newPalette, 1, 3, numToAdd);
-
- CTabHandle result = (CTabHandle)Get1Resource( 'clut', 128);
- DetachResource( (Handle)result);
-
- Palette2CTab( thePalette, result);
- DisposeHandle( (Handle)newPalette);
- return result;
- }
-
- PicHandle pixelize_shell::convertToPixMap(
- const PicHandle thePICT, short bitDepth,
- const CTabHandle theColorTable, Boolean transparent, short mode) const
- {
- Rect PICTRect = (**thePICT).picFrame;
- OffsetRect( &PICTRect, -PICTRect.left, -PICTRect.top);
-
- const short PICTWidth = PICTRect.right;
- const short PICTheight = PICTRect.bottom;
- //
- // convert the picture to a (large) picture containing only a pixmap
- //
- gworld offscreen( PICTWidth, PICTheight, bitDepth, true, theColorTable);
- offscreen.Set();
- DrawPicture( thePICT, &PICTRect);
-
- PicHandle result = 0L;
-
- if( transparent)
- {
- gworld mask( PICTWidth, PICTheight, 1);
- mask.Set();
- DrawPicture( thePICT, &PICTRect);
- RgnHandle maskRegion = mask.makeRegion();
- result = offscreen.makePICT( mode, maskRegion);
- DisposeRgn( maskRegion);
- } else {
- result = offscreen.makePICT( mode);
- }
- return result;
- }
-
- void pixelize_shell::WritePictFile( const fsspec &thefsspec, const PicHandle thePICT) const
- {
- OSErr err = noErr;
- //
- // Write a PICT Header first:
- // (to be safe, we write to a temporary file)
- //
- // BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT!
- // BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT!
- // BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT!
- //
- // We use a nice fail-safe strategy here. Unfortunately I don't know
- // whether that fail-safe strategy will work when the original file is not
- // on the boot volume. Do all volumes have a private temporary items folder?
- //
- // BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT!
- // BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT!
- // BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT! BUG ALERT!
- //
- fsspec tempFile( kTemporaryFolderType, "¥pPixelize temp" , thefsspec.vRefNum);
-
- tempFile.CreateUnique( 'ttxt', 'PICT');
-
- access_path tempAcess( tempFile, fsWrPerm);
- err = tempAcess();
-
- long FiveOneTwo = 0x0200;
- Ptr header = NewPtrClear( FiveOneTwo);
- err = tempAcess.SetFPos( 0x0000);
-
- err = tempAcess.Write( &FiveOneTwo, header);
-
- DisposePtr( header);
-
- if( err == noErr)
- {
- //
- // Then write the PICT itself:
- //
- long new_size = GetHandleSize( (Handle)thePICT);
- err = tempAcess.SetEOF( new_size + FiveOneTwo);
- err = tempAcess.SetFPos( FiveOneTwo);
-
- if( err == noErr)
- {
- HLock( (Handle)thePICT);
- err = tempAcess.Write( &new_size, *(Handle)thePICT);
- HUnlock( (Handle)thePICT);
- }
- if( err == noErr)
- {
- err = tempAcess.Close();
- if( err == noErr)
- {
- err = tempFile.ExchangeFiles( thefsspec);
- }
- }
- }
- tempFile.Delete();
- }
-
- void pixelize_shell::WritePictResource( const fsspec &thefsspec, const PicHandle thePICT) const
- {
- resourcefile thefile( thefsspec);
- OSErr err = thefile.Create();
- err = thefile.Open( fsRdWrPerm);
- err = thefile.Use();
- if( err == noErr)
- {
- AddResource( (Handle)thePICT, 'PICT', UniqueID( 'PICT'), "¥pConverted PICT");
- err = ResError();
- err = thefile.Update();
- DetachResource( (Handle)thePICT);
- err = thefile.Close();
- }
- }
-